備忘錄模式能讓物件在不破壞封裝的情況下儲存與回復狀態。
備忘錄模式的一個經典應用場景是歷史紀錄。這類紀錄在我們的日常生活中隨處可見,例如 Word、Photoshop 和 VS Code 等編輯軟體,都提供「上一步」和「下一步」功能,讓使用者在創作的過程中方便地復原或重做操作。這些歷史紀錄就像是備忘錄模式中的備忘錄,每個紀錄都代表著一個編輯狀態,你可以藉由切換紀錄來改變編輯狀態,從而改變編輯結果。
延續歷史紀錄的例子,我們來建立一個文字編輯軟體,並利用備忘錄模式來實現撤銷和重做功能。
EditorState
類別負責保存編輯器的狀態。它扮演備忘錄的角色,可以讓你保存目前的文字內容,並在需要的時候取出這些內容來恢復編輯器的內容。
class EditorState {
constructor(private content: string) {}
getContent(): string {
return this.content;
}
}
TextEditor
代表編輯器本身,負責更新文字內容和保存當前狀態。它也能根據提供的編輯器狀態來改變文字內容,你可以利用這項功能來撤銷或重做操作。
class TextEditor {
private content: string;
constructor(initialContent: string = "") {
this.content = initialContent;
}
updateContent(newContent: string) {
console.log(`TextEditor: Updating content to "${newContent}"`);
this.content = newContent;
}
createState(): EditorState {
return new EditorState(this.content);
}
restoreState(state: EditorState) {
const restoredContent = state.getContent();
console.log(
`TextEditor: Restoring content "${restoredContent}" from state`
);
this.content = restoredContent;
}
}
Application
是這個文字編輯軟體的主程式,負責管理編輯器和編輯器的歷史狀態。它可以讓使用者更新編輯器的內容,保存當前狀態,並撤銷和重做編輯內容。
class Application {
private states: EditorState[];
private currentIndex: number;
private textEditor: TextEditor;
constructor() {
this.states = [];
this.currentIndex = -1;
this.textEditor = new TextEditor();
}
updateContent(newContent: string) {
this.textEditor.updateContent(newContent);
this.states = this.states.slice(0, this.currentIndex + 1);
this.states.push(this.textEditor.createState());
this.currentIndex++;
}
undo() {
if (this.currentIndex > 0) {
this.currentIndex--;
this.textEditor.restoreState(this.states[this.currentIndex]);
}
}
redo() {
if (this.currentIndex < this.states.length - 1) {
this.currentIndex++;
this.textEditor.restoreState(this.states[this.currentIndex]);
}
}
}
我們初始化一個文字編輯軟體,更新幾次內容,然後重複撤銷和重做的操作,以展示狀態功能如何運作。
class ApplicationTestDrive {
static main() {
const app = new Application();
app.updateContent("I love coding.");
app.updateContent("I love listening to music.");
app.undo();
app.redo();
app.updateContent("I love drinking coffee.");
app.undo();
}
}
ApplicationTestDrive.main();
執行結果:
TextEditor: Updating content to "I love coding."
TextEditor: Updating content to "I love listening to music."
TextEditor: Restoring content "I love coding." from state
TextEditor: Restoring content "I love listening to music." from state
TextEditor: Updating content to "I love drinking coffee."
TextEditor: Restoring content "I love listening to music." from state
備忘錄模式是一種儲存物件狀態的方法,經常被用來實現回復和版本控制功能。物件可以將內部狀態儲存成備忘錄物件,並透過備忘錄物件來回復到特定的狀態。這種方法可以維持資料的封閉性,避免在儲存狀態資訊的同時將物件的內部資訊暴露於外。此外,它也能避免物件和狀態管理機制綁在一起,讓程式的設計變得更加靈活。
https://github.com/chengen0612/design-patterns-typescript/blob/main/patterns/behavioral/memento.ts